Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
safe-stable-stringify
Advanced tools
Deterministic and safely JSON.stringify to quickly serialize JavaScript objects
The safe-stable-stringify npm package is used to convert JavaScript objects into a JSON string representation in a deterministic order. It ensures that objects with the same content will result in the same JSON string, regardless of the order in which their properties were defined. It also handles circular references and other edge cases that can cause JSON.stringify to throw errors.
Deterministic JSON.stringify
This feature ensures that the JSON string output is consistent for the same object content, which is important for tasks like caching and comparison.
{"result": "safeStableStringify({ key1: 'value1', key2: 'value2' })"}
Handling circular references
safe-stable-stringify can handle objects that have circular references without throwing an error, unlike the native JSON.stringify.
{"result": "safeStableStringify(circularReference)"}
Custom replacer function
This feature allows for a custom replacer function to be used, similar to the replacer parameter in JSON.stringify, to customize the stringification process.
{"result": "safeStableStringify(obj, (key, value) => value instanceof RegExp ? String(value) : value)"}
This package offers similar functionality to safe-stable-stringify by providing a deterministic version of JSON.stringify. It ensures consistent ordering of object keys but does not handle circular references.
This is a faster implementation of json-stable-stringify without support for handling circular references. It is designed for performance-critical applications.
Flatted is a package that can serialize and deserialize objects with circular references to and from a flat JSON structure. It differs from safe-stable-stringify by focusing on the flat structure and the ability to reconstruct the original object, including circular references.
Safe, deterministic and fast serialization alternative to JSON.stringify. Zero dependencies. ESM and CJS. 100% coverage.
Gracefully handles circular structures and bigint instead of throwing.
Optional custom circular values, deterministic behavior or strict JSON compatibility check.
The same as JSON.stringify.
value
{any}replacer
{string[]|function|null}space
{number|string}const stringify = require('safe-stable-stringify')
const bigint = { a: 0, c: 2n, b: 1 }
stringify(bigint)
// '{"a":0,"b":1,"c":2}'
JSON.stringify(bigint)
// TypeError: Do not know how to serialize a BigInt
const circular = { b: 1, a: 0 }
circular.circular = circular
stringify(circular)
// '{"a":0,"b":1,"circular":"[Circular]"}'
JSON.stringify(circular)
// TypeError: Converting circular structure to JSON
stringify(circular, ['a', 'b'], 2)
// {
// "a": 0,
// "b": 1
// }
bigint
{boolean} If true
, bigint values are converted to a number. Otherwise
they are ignored. Default: true
.circularValue
{string|null|undefined|ErrorConstructor} Defines the value for
circular references. Set to undefined
, circular properties are not
serialized (array entries are replaced with null
). Set to Error
, to throw
on circular references. Default: '[Circular]'
.deterministic
{boolean|function} If true
or a Array#sort(comparator)
comparator method, guarantee a deterministic key order instead of relying on
the insertion order. Default: true
.maximumBreadth
{number} Maximum number of entries to serialize per object
(at least one). The serialized output contains information about how many
entries have not been serialized. Ignored properties are counted as well
(e.g., properties with symbol values). Using the array replacer overrules this
option. Default: Infinity
maximumDepth
{number} Maximum number of object nesting levels (at least 1)
that will be serialized. Objects at the maximum level are serialized as
'[Object]'
and arrays as '[Array]'
. Default: Infinity
strict
{boolean} Instead of handling any JSON value gracefully, throw an
error in case it may not be represented as JSON (functions, NaN, ...).
Circular values and bigint values throw as well in case either option is not
explicitly defined. Sets and Maps are not detected as well as Symbol keys!
Default: false
import { configure } from 'safe-stable-stringify'
const stringify = configure({
bigint: true,
circularValue: 'Magic circle!',
deterministic: false,
maximumDepth: 1,
maximumBreadth: 4
})
const circular = {
bigint: 999_999_999_999_999_999n,
typed: new Uint8Array(3),
deterministic: "I don't think so",
}
circular.circular = circular
circular.ignored = true
circular.alsoIgnored = 'Yes!'
const stringified = stringify(circular, null, 4)
console.log(stringified)
// {
// "bigint": 999999999999999999,
// "typed": "[Object]",
// "deterministic": "I don't think so",
// "circular": "Magic circle!",
// "...": "2 items not stringified"
// }
const throwOnCircular = configure({
circularValue: Error
})
throwOnCircular(circular);
// TypeError: Converting circular structure to JSON
[Circular]
(configurable).Number(5)
) are not unboxed and are handled as
regular object.Those are the only differences to JSON.stringify()
. This is a side effect free
variant and toJSON
, replacer
and the spacer
work the same as
with JSON.stringify()
.
Currently this is by far the fastest known stable (deterministic) stringify implementation. This is especially important for big objects and TypedArrays.
(Dell Precision 5540, i7-9850H CPU @ 2.60GHz, Node.js 16.11.1)
simple: simple object x 3,463,894 ops/sec ±0.44% (98 runs sampled)
simple: circular x 1,236,007 ops/sec ±0.46% (99 runs sampled)
simple: deep x 18,942 ops/sec ±0.41% (93 runs sampled)
simple: deep circular x 18,690 ops/sec ±0.72% (96 runs sampled)
replacer: simple object x 2,664,940 ops/sec ±0.31% (98 runs sampled)
replacer: circular x 1,015,981 ops/sec ±0.09% (99 runs sampled)
replacer: deep x 17,328 ops/sec ±0.38% (97 runs sampled)
replacer: deep circular x 17,071 ops/sec ±0.21% (98 runs sampled)
array: simple object x 3,869,608 ops/sec ±0.22% (98 runs sampled)
array: circular x 3,853,943 ops/sec ±0.45% (96 runs sampled)
array: deep x 3,563,227 ops/sec ±0.20% (100 runs sampled)
array: deep circular x 3,286,475 ops/sec ±0.07% (100 runs sampled)
indentation: simple object x 2,183,162 ops/sec ±0.66% (97 runs sampled)
indentation: circular x 872,538 ops/sec ±0.57% (98 runs sampled)
indentation: deep x 16,795 ops/sec ±0.48% (93 runs sampled)
indentation: deep circular x 16,443 ops/sec ±0.40% (97 runs sampled)
Comparing safe-stable-stringify
with known alternatives:
fast-json-stable-stringify x 18,765 ops/sec ±0.71% (94 runs sampled)
json-stable-stringify x 13,870 ops/sec ±0.72% (94 runs sampled)
fast-stable-stringify x 21,343 ops/sec ±0.33% (95 runs sampled)
faster-stable-stringify x 17,707 ops/sec ±0.44% (97 runs sampled)
json-stringify-deterministic x 11,208 ops/sec ±0.57% (98 runs sampled)
fast-safe-stringify x 21,460 ops/sec ±0.75% (99 runs sampled)
this x 30,367 ops/sec ±0.39% (96 runs sampled)
The fastest is this
The fast-safe-stringify
comparison uses the modules stable implementation.
Sponsored by MaibornWolff and nearForm
MIT
v2.5.0
Array#sort(comparator)
comparator method as deterministic option value to use that comparator for sorting object keys.import { configure } from 'safe-stable-stringify'
const object = {
a: 1,
b: 2,
c: 3,
}
const stringify = configure({
deterministic: (a, b) => b.localeCompare(a)
})
stringify(object)
// '{"c":3,"b":2,"a":1}'
Thanks to @flobernd, @cesco69 and @prisis to contribute to this release!
FAQs
Deterministic and safely JSON.stringify to quickly serialize JavaScript objects
The npm package safe-stable-stringify receives a total of 8,892,879 weekly downloads. As such, safe-stable-stringify popularity was classified as popular.
We found that safe-stable-stringify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.